package main;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

import hmove.MoveFly;
import hmove.MoveRazorLeaf;
import hmove.Move;
import java.io.IOException;

import java.util.Random;
import java.util.Vector;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.game.GameCanvas;
import javax.microedition.lcdui.game.LayerManager;
import javax.microedition.lcdui.game.Sprite;

/**
 *
 * @author  Karel Herink
 * @version 1.0
 */
public class PlayingCanvas extends GameCanvas implements Runnable, CommandListener {

    private static final int FREE_STATE = 0;
    private static final int POWER_UP_STATE = 1;
    private static final int FIRING_STATE = 2;
    private static final int HP_DOWN_STATE = 3;
    private static final int MAX_POWER = 80;
    private int gameState;
    private MainMidlet midlet;
    private boolean isPlaying;
    private Sprite map;
    private LayerManager layerManager;
    private int viewportX;
    private int viewportY;
    private int firePow;
    private Sprite observeSprite;
    private PokemonTeam[] _pokemonTeam;
    private Vector _listEffectedPokemon = new Vector();
    private Pokemon currentPokemon;
    private Move _currentMove;
    //private int turn = 0;//show up which team's turn;
    private Random random = new Random();

    //
    private Command cmd = new Command("Back", Command.BACK, 0);
    private Item item;
    private Character character;
    private boolean isFreeBattle;
    //
    public PlayingCanvas(MainMidlet midlet, Character character, Pokemon pokemon2, Item item, boolean isFreeBattle) {
        super(true);
        try {
            this.setFullScreenMode(true);
            this.init(character.getOwnPokemon(), pokemon2);

        } catch (IOException ex) {
            ex.printStackTrace();
        }
        this.midlet = midlet;
        this.character = character;
        this.item = item;
        this.addCommand(cmd);
        this.setCommandListener(this);
        this.isFreeBattle = isFreeBattle;
    }
    
    private void init(Pokemon pokemon1, Pokemon pokemon2) throws IOException {
        _pokemonTeam = new PokemonTeam[2];
        for (int i = 0; i < _pokemonTeam.length; i++) {
            _pokemonTeam[i] = new PokemonTeam();
        }

        gameState = FREE_STATE;

        layerManager = new LayerManager();

//        Pokemon pokemon1 = new Pokemon("/Bubasas.png", 41, 41, 6, 4, 2, 2);
//        Pokemon pokemon2 = new Pokemon("/Pidgey.png", 30, 30, 4, 4, 2, 4);

        _pokemonTeam[0].setColor(0x00FF0000);
        _pokemonTeam[1].setColor(0x000000FF);
        _pokemonTeam[0].add(pokemon1);
        _pokemonTeam[1].add(pokemon2);
        //_pokemonTeam[0].add(new Pokemon("/Bubasas.png", 41, 41, 6, 4, 2, 2));
        //_pokemonTeam[0].add(new Pokemon("/Bubasas.png", 41, 41, 6, 4, 2, 2));
        //_pokemonTeam[0].add(new Pokemon("/Pidgey.png", 30, 30, 4, 4, 2, 4));
        //_pokemonTeam[1].add(new Pokemon("/Pidgey.png", 30, 30, 4, 4, 2, 4));
        //_pokemonTeam[1].add(new Pokemon("/Pidgey.png", 30, 30, 4, 4, 2, 4));
        //_pokemonTeam[1].add(new Pokemon("/Bubasas.png", 41, 41, 6, 4, 2, 2));
        /*_pokemonTeam[0].add(new Pokemon("/Bubasas.png", 41, 41, 6, 4, 2, 2));
        _pokemonTeam[0].add(new Pokemon("/Bubasas.png", 41, 41, 6, 4, 2, 2));
        _pokemonTeam[0].add(new Pokemon("/Pidgey.png", 30, 30, 4, 4, 2, 4));
        _pokemonTeam[1].add(new Pokemon("/Pidgey.png", 30, 30, 4, 4, 2, 4));
        _pokemonTeam[1].add(new Pokemon("/Pidgey.png", 30, 30, 4, 4, 2, 4));
        _pokemonTeam[1].add(new Pokemon("/Bubasas.png", 41, 41, 6, 4, 2, 2));
        _pokemonTeam[0].add(new Pokemon("/Bubasas.png", 41, 41, 6, 4, 2, 2));
        _pokemonTeam[0].add(new Pokemon("/Bubasas.png", 41, 41, 6, 4, 2, 2));
        _pokemonTeam[0].add(new Pokemon("/Pidgey.png", 30, 30, 4, 4, 2, 4));
        _pokemonTeam[1].add(new Pokemon("/Pidgey.png", 30, 30, 4, 4, 2, 4));
        _pokemonTeam[1].add(new Pokemon("/Pidgey.png", 30, 30, 4, 4, 2, 4));
        _pokemonTeam[1].add(new Pokemon("/Bubasas.png", 41, 41, 6, 4, 2, 2));/**/
        map = new Sprite(Image.createImage("/map.png"));
        for (int i = 0; i < _pokemonTeam.length; i++) {
            for (int j = 0; j < _pokemonTeam[i].count(); j++) {

                _pokemonTeam[i].getPokemonAt(j).getSprite().setPosition(200+200 * i + j * 20, 0);
                layerManager.append(_pokemonTeam[i].getPokemonAt(j).getSprite());
            }
        }


        Sprite sky = new Sprite(Image.createImage("/sky.png"));
        layerManager.append(map);
        layerManager.append(sky);

        /*pokemon1.getSprite().setPosition(100, 10);
        pokemon2.getSprite().setPosition(150, 10);*/
        firePow = 0;
        newRound();
    }

    public void start() {
        Thread t = new Thread(this);
        t.start();
        isPlaying = true;
    }

    private void adjustViewport(Sprite sp) {
        int x = sp.getX();
        int y = sp.getY();

        x = x + sp.getWidth() / 2 - getWidth() / 2;
        y = y + sp.getHeight() / 2 - getHeight() / 2;

        int dx = x - viewportX;
        int dy = y - viewportY;

        int dis = 25;
        if (dx * dx + dy * dy > dis * dis) {

            float m;
            if (dx > dy) {
                m = (float) dy / dx;
                dx = (int) (dis / Math.sqrt((double) (m * m + 1)));
                dy = (int) (m * dis / Math.sqrt((double) (m * m + 1)));
            } else {
                m = (float) dx / dy;
                dy = (int) (dis / Math.sqrt((double) (m * m + 1)));
                dx = (int) (m * dis / Math.sqrt((double) (m * m + 1)));
            }
            x = viewportX + dx;
            y = viewportY + dy;
        }

        if (x < -0) {
            x = 0;
        } else if (x > map.getWidth() - getWidth()) {
            x = map.getWidth() - getWidth();
        }

        if (y > map.getHeight() - getHeight()) {
            y = map.getHeight() - getHeight();
        }

        viewportX = x;
        viewportY = y;
        layerManager.setViewWindow(x, y, getWidth(), getHeight());
    }

    private void newRound() {
        for (int i = 0; i < _pokemonTeam.length; i++) {
            _pokemonTeam[i].buildPokemonControlList();
        }
        newTurn();
    }

    private void newTurn() {
        int maxSpeed = -1;
        int teamIndex = -1;

        for (int i = 0; i < _pokemonTeam.length; i++) {

            Pokemon pokemon = _pokemonTeam[i].getPokemon();
            if (pokemon != null && pokemon.getSpeed() > maxSpeed) {
                maxSpeed = pokemon.getSpeed();
                teamIndex = i;
            }
        }
        if (teamIndex < 0) {
            newRound();
            return;
        }
        currentPokemon = _pokemonTeam[teamIndex].getPokemon();
        observeSprite = currentPokemon.getSprite();
        _pokemonTeam[teamIndex].removePokemon();
        gameState = FREE_STATE;
        firePow = 0;


    }

    public void run() {
        Graphics g = getGraphics();
        while (isPlaying) {
            input();
            adjustViewport(observeSprite);


            if (gameState == FIRING_STATE)// firing moment
            {
                boolean flag = _currentMove.run(map);
                for (int i = 0; i < _pokemonTeam.length; i++) {
                    for (int j = 0; j < _pokemonTeam[i].count(); j++) {
                        Pokemon pokemon = _pokemonTeam[i].getPokemonAt(j);

                        boolean isHit = _currentMove.hit(pokemon);
                        if (isHit) {
                            
                            _listEffectedPokemon.addElement(pokemon);
                        }

                    }
                }
                if (flag) {

                    gameState = HP_DOWN_STATE;
                }
                //finish firing
            } else if (gameState == HP_DOWN_STATE)//some pokemon are hit by the attack, start hp down effect
            {
                if (_listEffectedPokemon.isEmpty()) {
                    gameState = FREE_STATE;//finish hp down effect, new turn
                    newTurn();
                } else {
                    Pokemon pokemon = (Pokemon) _listEffectedPokemon.firstElement();
                    pokemon.beHit();
                    currentPokemon = pokemon;
                    observeSprite = pokemon.getSprite();
                    if (pokemon.alterHp()) {
                        pokemon.Stand();
                        _listEffectedPokemon.removeElementAt(0);
                        if (pokemon.getHp() <= 0) {
                            layerManager.remove(pokemon.getSprite());
                        }
                    }

                }
            }

            for (int i = 0; i < _pokemonTeam.length; i++) {
                for (int j = 0; j < _pokemonTeam[i].count(); j++) {
                    _pokemonTeam[i].getPokemonAt(j).run(map);
                }
            }
            display(g);

            try {
                Thread.sleep(100);
            } catch (InterruptedException ex) {
            }
        }
    }

    private void input() {
        int key = getKeyStates();
        if ((key & FIRE_PRESSED) != 0) {
            if (gameState == FREE_STATE) {
                int r = random.nextInt(2);
                //if (r == 1) {
                    _currentMove = new MoveRazorLeaf(currentPokemon);
                /*} else {
                    _currentMove = new MoveFly(currentPokemon);
                }*/
                //currentPokemon.Fire();
                gameState = POWER_UP_STATE;//Fire down, power up
            } else if (gameState == POWER_UP_STATE) {
                System.out.print("Power up");
                if (firePow < MAX_POWER) {
                    firePow += 3;
                }
            }
        } else if (gameState == POWER_UP_STATE) {//Fire release
            // start firing here
            System.out.print("Fire");

            observeSprite = _currentMove.getObserveSprite();
            _currentMove.activate(firePow);
            gameState = FIRING_STATE;
            //currentPokemon.Stand();

        } else if (gameState == FREE_STATE) {// free state, you can move
            if ((key & LEFT_PRESSED) != 0) {
                currentPokemon.Move(true, map);
            } else if ((key & RIGHT_PRESSED) != 0) {
                currentPokemon.Move(false, map);
            } else if ((key & UP_PRESSED) != 0) {
                currentPokemon.gunUp();
            } else if ((key & DOWN_PRESSED) != 0) {
                currentPokemon.gunDown();
            } else {
                currentPokemon.Stand();
            }
        }

    }

    private void display(Graphics g) {
        g.setColor(0x005088a0);
        g.fillRect(0, 0, getWidth(), getHeight());

        layerManager.paint(g, 0, 0);

        currentPokemon.paint(g, -viewportX, -viewportY,true,gameState==FREE_STATE);
        if (gameState == FIRING_STATE) {
            _currentMove.paint(g, -viewportX, -viewportY);
        }
        drawMenu(g);

        //g.fillRoundRect(0, 0, firePow,10,5,5);
        flushGraphics();

    }

    private void drawMenu(Graphics g) {
        g.setColor(0x00FF0000);
        g.fillRect(0, 10, firePow, 2);
        g.setColor(0x00800000);
        g.fillRect(0, 12, firePow, 3);

        g.setColor(0x00FFFFFF);
        g.drawLine(0, 15, MAX_POWER, 15);

        g.drawString("POWER", 0, 15, 0);
        int d = MAX_POWER / 5;
        for (int i = 0; i <= 5; i++) {
            g.drawLine(i * d, 10, i * d, 15);
            g.drawString(String.valueOf(i), i * d, 0, 0);
        }

        g.drawString(String.valueOf((int) (currentPokemon.getAngle() * 180 / Math.PI)), MAX_POWER + 20, 0, 0);
        g.drawString("ARC", MAX_POWER + 20, 15, 0);
    }

    public void stop() {
        isPlaying = false;
    }

    public void commandAction(Command c, Displayable d) {
        if(c == cmd)
        {
            stop();
            if(isFreeBattle)
                midlet.showMainMenu();
            else
                midlet.showStoryModeMenuOption(item, character);
        }
    }
}
